/**
 * 开发者   : Marco
 * 创建时间 : 2016年7月19日, 下午8:38
 */

#include "basic.h"

#include <map>
#include <string.h>
#include <stdio.h>

#ifndef MARCO_NO_HTTP

MARCOPP_NAMESPACE_BEGIN
MARCOPP_NAMESPACE_HTTP_BEGIN

/** 实现类
 */
class basic_impl {
public:
    basic_impl(version_type version) : version(version) {}
    
    version_type get_version(void) const { return version; }
    void set_version(version_type version) { this->version = version; }
    
    /**
     * 特定消息报头
     */
    void set_content_length(int content_length) {   // 设置协议头中Content-Length, 正文长度
	char tmp[20]; sprintf(tmp, "%d", content_length); set_msghead("Content-Length", tmp);
    }
     
    void set_real_content_length(void) {	    // 根据正文内容长度, 设置协议头中的Content-Length头
	char tmp[20]; sprintf(tmp, "%ld", content_str.size()); set_msghead("Content-Length", tmp);
    }
    
    void set_cache_control(const char* cache_str) { set_msghead("Cache-Control", cache_str); } // 设置协议头中Cache-Control, 缓存控制
    void set_content_type(content_type ctype) {	// 设置协议头中Content-Type, 正文格式
	string content_type_str;
	string name("Content-Type");
	
	switch (ctype) {
	case content_json_utf8:
	    content_type_str = "application/json; charset=UTF-8";
	    break;
	case content_texthtml_utf8:
	    content_type_str = "text/html; charset=UTF-8";
	default : return;
	}
	
	set_msghead(name, content_type_str);
    }
    
    /**
     * 初始化各head头, 作为键值对保存 Content-Length: 201931
     * @param data 首个head首地址, 会修改原内容.
     * @return 结果
     */
    bool init_msghead(char* data) {
	char *ptr, *value;
	
	while ((ptr = strstr(data, "\r\n"))) {
	    *ptr = 0;	// 截断
	    ptr += 2;	// 指向下一行head首地址
	    
	    if (!(value = strchr(data, ':'))) return false; // key与value分隔符
	    
	    *value = 0;
	    value += 2;	// 指向value, 冒号后有一个空格
	    
	    if (value >= ptr) return false; // 空值
	    
	    msgheads.insert(std::pair<string, string>(data, value));
	    data = ptr;
	}
	
	return true;
    }
    
    /**
     * 消息报头设置与获取
     */
    void set_msghead(string& name, string& value) {  // 设置一条消息报头
	msgheads.insert(std::pair<string, string>(name, value)); 
    } 
    void set_msghead(const char* name, const char* value) {    // 设置一条消息报头
	msgheads.insert(std::pair<string, string>(name, value)); 
    }
    const char* get_msghead(const char* name) {	// 获取一条消息报头
	std::map<string, string>::iterator it = msgheads.find(name);
	
	if (it != msgheads.end()) {
	    return it->second.c_str();
	}
	
	return NULL;
    }
    
    void get_msghead_str(string& buf) {   // 获取http头字符串格式
	std::map<string, string>::iterator it = msgheads.begin();
	std::map<string, string>::iterator end = msgheads.end();

	while (it != end) {
	    buf += it->first;
	    buf += ": ";
	    buf += it->second;
	    buf += "\r\n";
	    ++it;
	}
    }
    
    int get_msghead_str(char* buf) {   // 获取http头字符串, 由用户提供足够大空间
	int len = 0, ret;
	std::map<string, string>::iterator it = msgheads.begin();
	std::map<string, string>::iterator end = msgheads.end();

	while (it != end) {
	    ret = sprintf(buf+len, "%s: %s\r\n", it->first.c_str(), it->second.c_str());
	    len += ret;
	    ++it;
	}
	
	return len;
    }
    
    /**
     * 正文
     * @param content_str
     */
    void append_content_str(string& content_str) { this->content_str += content_str; }
    void append_content_str(const char* content_str) { this->content_str += content_str; }
    void append_content_str(const char* content_str, int len) { this->content_str.append(content_str, len); }
    bool is_content_empty(void) const {	return content_str.empty(); }
    string& get_content_str(void) { return content_str; }
    const char* get_content_ptr(void) const { return content_str.c_str(); }
    int get_content_length(void) const { return (int)content_str.length(); }
    
private:
    version_type version;			    // 版本
    std::map<string, string> msgheads;    // 消息报头
    string content_str;			    // 正文内容
};


basic::basic(version_type version) : impl(new basic_impl(version)) {}
basic::~basic(void) { delete impl; }

version_type basic::get_version(void) const { return impl->get_version(); }
void basic::set_version(version_type version) { impl->set_version(version); }

/**
 * 消息报头处理
 */
void basic::set_content_length(int content_length) { impl->set_content_length(content_length); }
void basic::set_real_content_length(void) { impl->set_real_content_length(); }
void basic::set_cache_control(const char* cache_str) { impl->set_cache_control(cache_str); }
void basic::set_content_type(content_type ctype) { impl->set_content_type(ctype); }

bool basic::init_msghead(char* data) { return impl->init_msghead(data); }	    // 从协议数据中初始化消息报头
void basic::set_msghead(string& name, string& value) { impl->set_msghead(name, value); }  // 设置一条消息报头
void basic::set_msghead(const char* name, const char* value) { impl->set_msghead(name, value); }    
const char* basic::get_msghead(const char* name) { return impl->get_msghead(name); }	// 获取一条消息报头
void basic::get_msghead_str(string& buf) { impl->get_msghead_str(buf); }	// 获取消息报头字符串形式
int basic::get_msghead_str(char* buf) { return impl->get_msghead_str(buf); }	

/**
 * 正文处理
 */
void basic::append_content_str(string& content_str) { impl->append_content_str(content_str); } // 追加正文内容
void basic::append_content_str(const char* content_str) { impl->append_content_str(content_str); }
void basic::append_content_str(const char* content_str, int len) { impl->append_content_str(content_str, len); }
bool basic::is_content_empty(void) const { return impl->is_content_empty(); }	    // 正文是否为空
string& basic::get_content_str(void) { return impl->get_content_str(); }	    // 获取正文内容
const char* basic::get_content_ptr(void) const { return impl->get_content_ptr(); }
int basic::get_content_length() const { return impl->get_content_length(); }


MARCOPP_NAMESPACE_HTTP_END
MARCOPP_NAMESPACE_END
#endif // MARCO_NO_HTTP
